/*
 *
 */

#ifndef GKT_USER_H
#define GKT_USER_H

#include "gkt_types.h"

#ifdef __cplusplus
extern "C" {
#endif

#include "gkt_user_defines.h"

/* user authority */
enum {
	GKT_USER_AUTH_ADMIN = 0,	/* admin user, manager & open door without limit */
	GKT_USER_AUTH_NORMAL,	/* normal user, open door without limit */
	GKT_USER_AUTH_GUEST,	/* guest user, open door with limit */
	GKT_USER_AUTH_THREATEN, /* threaten user, open door without limit. belong to normal user */
	GKT_USER_AUTH_TEMPORARY = GKT_USER_AUTH_THREATEN,	/* temporary user, e.g: One-Time-Password user */
	GKT_USER_AUTH_MAX
};

/* user type */
enum {
	/* local user type */
	GKT_USER_TYPE_FINGERPRINT = 0,
#if defined(GKT_CONFIG_KEYPAD_ENABLE) && GKT_CONFIG_KEYPAD_ENABLE
	GKT_USER_TYPE_PASSWORD,
#endif
#if defined(GKT_CONFIG_RFID_ENABLE) && GKT_CONFIG_RFID_ENABLE
	GKT_USER_TYPE_CARD,	/* NFC/RFID Card */
#endif
#if defined(GKT_CONFIG_FACE_ID_ENABLE) && GKT_CONFIG_FACE_ID_ENABLE
	GKT_USER_TYPE_FACE_ID,
#if defined(GKT_CONFIG_PALM_ENABLE) && GKT_CONFIG_PALM_ENABLE
	GKT_USER_TYPE_PALM,
#endif
#endif
	GKT_USER_TYPE_MAX,

	GKT_USER_TYPE_DYNPWD = 0xF0,	/* dynamic password */
};

/* user extented type of password */
enum {
	GKT_USER_PASSWORD_NORMAL = 0,
	GKT_USER_PASSWORD_TOTP,	/* Time-based One-time Password */
	GKT_USER_PASSWORD_NOTS,	/* number of times */
	GKT_USER_PASSWORD_EDTQ,	/* expiration date & time quantum */
	GKT_USER_PASSWORD_SDED,	/* start date & expiration date */
	GKT_USER_PASSWORD_MAX
};

#define GKT_USER_TYPE_SPECIAL	0x0F
/* user extended type of SPECIAL */
enum {
	GKT_USER_TYPE_SPECIAL_REMOTE = 0,
	GKT_USER_TYPE_SPECIAL_BLE,
	GKT_USER_TYPE_SPECIAL_MAX
};

typedef struct _gkt_user_amount {
	uint32_t	max_nums;
	uint32_t	used_nums;
} gkt_user_amount_s;

/* enroll result */
enum {
	/* success */
	GKT_USER_ENROLL_COMPLETE = 0,

	/* continue */
	GKT_USER_ENROLL_SUCCESS_CONTINUE,
	GKT_USER_ENROLL_FAILED_CONTINUE,
	GKT_USER_ENROLL_MOVE_MORE,
	GKT_USER_ENROLL_MOVE_LESS,
	
	/* error */
	GKT_USER_ENROLL_ERROR,
	GKT_USER_ENROLL_EXIST,
	GKT_USER_ENROLL_UNAVAILABLE,
	GKT_USER_ENROLL_OVERMUCH,
	GKT_USER_ENROLL_UNSUPPORT,

	GKT_USER_ENROLL_MAX
};

/* verify result */
enum {
	GKT_USER_VERIFY_PASSED = 0,
	GKT_USER_VERIFY_PASSED_UPDATE,
	GKT_USER_VERIFY_INVALID_ACCESS_TIME,
	GKT_USER_VERIFY_CANCELLED,
	GKT_USER_VERIFY_FAILED,
	GKT_USER_VERIFY_MAX
};

typedef struct _gkt_user_password_cfg_params {
	int	simple_password_enable;
	int	similar_password_enable;
} gkt_user_password_cfg_params_s;

typedef struct _gkt_user_cfg_params {
	gkt_user_password_cfg_params_s	password;
	/* other members ... */
} gkt_user_cfg_params_s;

uint32_t gkt_user_get_id(uint32_t user_index);

/*
 * @function : gkt_user_get_amount
 * @brief    : get user amount
 * @example  :
 *   1. gkt_user_get_amount(amount, GKT_USER_AUTH_ADMIN, GKT_USER_TYPE_FINGER)
 *      get user amount of ADMIN & FINGER
 *   2. gkt_user_get_amount(amount, GKT_USER_AUTH_GUEST, GKT_USER_TYPE_MAX)
 *      get user amount of GUEST
 *   3. gkt_user_get_amount(amount, GKT_USER_AUTH_MAX, GKT_USER_TYPE_CARD)
 *      get user amount of CARD
 *   4. gkt_user_get_amount(amount, GKT_USER_AUTH_MAX, GKT_USER_TYPE_MAX)
 *      get all user amount of all AUTH & TYPE
 */
int gkt_user_get_amount(gkt_user_amount_s *amount,
			uint32_t authority, uint32_t type);

/*
 * @function gkt_user_verify
 * @brief    verify user
 * @params
 *   id [out] the user identification info if authentication passed
 *   type    [in] USER_TYPE_FINGER/PASSWORD/...
 *   data    [in] identification data, e.g: password text
 *   len     [in] identification data length, e.g: password text length
 * @return value
 *   USER_VERIFY_PASSED (0) : verify pased, authorized user
 *   USER_VERIFY_XXX        : verify failed
 *   < 0 : error occurs during verify operation, could not authenticate the user
 */
int gkt_user_verify(uint32_t *user_id, uint32_t type, 
				uint32_t authority, const void *data, uint32_t length);

/*
 * @function : gkt_user_verify_update
 */
void gkt_user_verify_update(uint32_t type);

/*
 * @function : gkt_user_get_free_index
 * @brief    : get an available/free user index
 * @retval   : success - (GKT_USER_INDEX_MIN, GKT_USER_INDEX_MAX)
 *             failed  - others
 */
uint32_t gkt_user_get_free_index(uint32_t authority);


/*
 * @function : gkt_user_enroll_init
 * @brief    : int enroll procedure
 */
int gkt_user_enroll_init(uint32_t user_index, 
			uint32_t authority, uint32_t threaten, uint32_t type);

/*
 * @function : gkt_user_enroll_run
 * @brief    : enroll run
 */
int gkt_user_enroll(uint32_t type,
			const void *data, uint32_t len);

/*
 * @function : gkt_user_delete_index
 * @brief    : delete the user specified by user_index
 */
void gkt_user_delete_index(uint32_t user_index);

/*
 * @function : gkt_user_delete_group
 * @brief    : delete all user of group specified authority & type
 * @example  :
 *   1. delete all guest users: gkt_user_delete_group(AUTH_GUEST, TYPE_MAX)
 *   2. delete all card users: gkt_user_delete_group(AUTH_MAX, TYPE_CARD)
 *   3. delete all guest & card users: gkt_user_delete_group(AUTH_GUEST, TYPE_CARD)
 *   4. forbidden condition: gkt_user_delete_group(AUTH_MAX, TYPE_MAX)
 */
void gkt_user_delete_group(uint32_t authority, uint32_t type);

int gkt_user_reset(void);

int gkt_user_init(void);

int gkt_user_config(gkt_user_cfg_params_s *cfg_params);

#ifdef __cplusplus
}
#endif

#endif	/* GKT_USER_H */

